home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 201-225 / disk_217 / snipit / main.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  14KB  |  691 lines

  1. /* :ts=4
  2.  *
  3.  * Amiga SnipIt 1.2
  4.  * (c) (opyright 1987,1988 - Scott Evernden - All Rights Reserved
  5.  *
  6.  * main.c - cutter/paster like SunTools
  7.  *
  8.  * Permission is granted to modify and redistribute as long
  9.  * as this notice is left intact.
  10.  *
  11.  */
  12.  
  13. /**********************
  14.  
  15.     The strategy here begins with the installation of some input handler
  16.     code into the input event handler chain.  This code looks for mouse
  17.     actions and keyboard presses that indicate that text is being snipped,
  18.     or is being pasted.
  19.  
  20.     Snipped text (plane 0) is always immediately copied into a temp 1-plane
  21.     bitmap without further processing.  Subsequents "snips" cause the old
  22.     snipped bitmap to be thrown away, and a new one captured.
  23.  
  24.     Pasting requires that the text in the capture bitmap be recognized.
  25.     This is not done in the input handler code, since it would cause all
  26.     pending input events to pile up while the recognizer is running.
  27.     Instead, the input handler code signals the main snipit code (RUNning
  28.     in the background, itself) to do the recognition and fake the kb events.
  29.     During this period, the input handler code temporarily suspends its
  30.     special processing waiting for the main code (recognizer) to finish.
  31.  
  32.     Once a capture bitmap has been recognized and converted into a sequence
  33.     of key codes, it is deallocated, and subsequent pastes don't require
  34.     the recognition step.
  35.  
  36. **********************/
  37.  
  38. #include "hs.h"
  39.  
  40. struct Task *_FindTask();
  41. struct Library *_OpenLibrary();
  42.  
  43. BPTR output = 0;
  44.  
  45. long LayersBase;                    /* for WhichLayer() */
  46. struct GfxBase *GfxBase;
  47. struct IntuitionBase *IntuitionBase;
  48. struct ConsoleBase *ConsoleBase;    /* defined in hs.h */
  49.  
  50. /* communication with input.device */
  51. struct IOStdReq *inpReq;
  52. struct MsgPort *inpPort;
  53.  
  54. /* communication with console.device */
  55. struct MsgPort *conPort;
  56. struct IOStdReq *conReq;
  57.  
  58. /* who I am */
  59. struct Task *myTask;
  60.  
  61. /* snipit's port */
  62. struct MsgPort *myPort;
  63.  
  64. struct MyMessage {
  65.     struct Message m;
  66.     int done, huh, off;
  67.     int w_offx, w_offy;
  68.     int c_offx, c_offy;
  69.     long alen;
  70.     char *aptr;
  71. } myMsg, *msgp;
  72.  
  73. /* for snipit's input handler */
  74. struct Interrupt handler;
  75.  
  76. /* flags handler installation for cleanup */
  77. int handlerIn;
  78.  
  79. /* snipit's allocated signal bit */
  80. int mySignal = -1L;
  81.  
  82. /* snipit's input handler code */
  83. VOID handlerCode();
  84.  
  85. /* snipit replacement functions */
  86. VOID myRectFill(), myScrollRaster(), myCloseWindow();
  87.  
  88. /* remember original library vectors */
  89. long oldRectFill, oldScrollRaster, oldCloseWindow;
  90.  
  91. /* vector offsets of certain functions */
  92. extern int lvoRectFill, lvoScrollRaster, lvoCloseWindow;
  93.  
  94. /* detach stuff */
  95. long running = 0;
  96. char *_procname = "\x9B33mSnipIt 1.2\x9B0m";
  97.  
  98. char *huh_msg =   "Huh?  (for help type: snipit h)";
  99.  
  100. /* "Can't open"... forms */
  101. char *i_libname = "~intuition.library";
  102. char *g_libname = "~graphics.library";
  103. char *l_libname = "~layers.library";
  104. char *i_devname = "~input.device";
  105. char *c_devname = "~console.device";
  106.  
  107. char *port_name = "^\x9B33mSnipIt 1.2\x9B0m Port";
  108.  
  109. long _savsp;
  110.  
  111. extern int jobFlag;
  112. extern int con_offx, con_offy;
  113. extern int win_offx, win_offy;
  114. extern int cmd1, cmd2;
  115. extern int snip, lock_layer, windows;
  116. extern char preString[];
  117.  
  118. /*********************************************/
  119. /* pick up the ABS symbols describing gfx/intui lib offsets
  120.  */
  121. #asm
  122.     dseg
  123.     public    _LVORectFill
  124.     public    _LVOScrollRaster
  125.     public    _LVOCloseWindow
  126.  
  127. _lvoRectFill        dc.w    _LVORectFill
  128. _lvoScrollRaster    dc.w    _LVOScrollRaster
  129. _lvoCloseWindow        dc.w    _LVOCloseWindow
  130.  
  131.     cseg
  132. #endasm
  133.  
  134. /*********************************************/
  135.  
  136. writes(str)
  137. register char *str;
  138. {
  139.     register char *piece;
  140.     register long len;
  141.  
  142.     len = 0;
  143.  
  144.     if (*str == '!') {
  145.         piece = "Can't ";
  146.         len = 6;
  147.     }
  148.     else if (*str == '~') {
  149.         piece = "Can't open ";
  150.         len = 11;
  151.     }
  152.     else if (*str == '^') {
  153.         piece = "Can't create ";
  154.         len = 13;
  155.     }
  156.     else if (*str == '_') {
  157.         piece = _procname;
  158.         len = 17;
  159.     }
  160.  
  161.     if (len) {
  162.         str++;
  163.         _Write(output, piece, len);
  164.     }
  165.  
  166.     /* output a message & newline */
  167.     _Write(output, str, (long) strlen(str));
  168.     _Write(output, "\n", 1L);
  169. }
  170.  
  171. /*********************************************/
  172.  
  173. fini()
  174. {
  175.     long stat;
  176.  
  177.     /* cleanup in other modules */
  178.     finiHand();
  179.     finiReco();
  180.  
  181.     /* restore gfx/intui library vectors */
  182.     if (oldRectFill)
  183.         SetFunction(GfxBase, (long) lvoRectFill, oldRectFill);
  184.  
  185.     if (oldScrollRaster)
  186.         SetFunction(GfxBase, (long) lvoScrollRaster, oldScrollRaster);
  187.  
  188.     if (oldCloseWindow)
  189.         SetFunction(IntuitionBase, (long) lvoCloseWindow, oldCloseWindow);
  190.  
  191.     /* remove snipit input handler */
  192.     if (handlerIn) {
  193.         inpReq->io_Command = IND_REMHANDLER;
  194.         inpReq->io_Data = (APTR) &handler;
  195.         DoIO(inpReq);
  196.     }
  197.  
  198.     /* close down console.device */
  199.     if (conReq) {
  200.         if (conReq->io_Device)
  201.             CloseDevice(conReq);
  202.         DeleteStdIO(conReq);
  203.     }
  204.     if (conPort)
  205.         DeletePort(conPort);
  206.  
  207.     /* close down input.device */
  208.     if (inpReq) {
  209.         if (inpReq->io_Device)
  210.             CloseDevice(inpReq);
  211.         DeleteStdIO(inpReq);
  212.     }
  213.     if (inpPort)
  214.         DeletePort(inpPort);
  215.  
  216.     /* release snipit's port & signal bit */
  217.     if (myPort)
  218.         DeletePort(myPort);
  219.  
  220.     if (mySignal != -1)
  221.         FreeSignal(1L << mySignal);
  222.  
  223.     /* close libraries */
  224.     if (GfxBase)
  225.         _CloseLibrary(GfxBase);
  226.  
  227.     if (LayersBase)
  228.         _CloseLibrary(LayersBase);
  229.  
  230.     if (IntuitionBase)
  231.         _CloseLibrary(IntuitionBase);
  232.  
  233.     if (output)
  234.         _Close(output);
  235.  
  236. #asm
  237.     moveq    #0,d0            ;pick up return exit code
  238.     move.l    __savsp,sp        ;get back original stack pointer
  239.     rts                        ;and exit
  240. #endasm
  241. }
  242.  
  243. /*********************************************/
  244.  
  245. int init()
  246. {
  247.     long stat;
  248.  
  249.     /* global record of this task's ID */
  250.     myTask = _FindTask((char *) NULL);
  251.  
  252.     /* need intuitionbase to read mouse pos. & screen layer */
  253.     IntuitionBase = (struct IntuitionBase *) _OpenLibrary(i_libname + 1, 0L);
  254.     if (IntuitionBase == NULL) {
  255.         writes(i_libname);
  256.         return 0;
  257.     }
  258.  
  259.     /* need graphics since we do */
  260.     GfxBase = (struct GfxBase *) _OpenLibrary(g_libname + 1, 0L);
  261.     if (GfxBase == NULL) {
  262.         writes(g_libname);
  263.         return 0;
  264.     }
  265.  
  266.     /* layers for WhichLayer() */
  267.     LayersBase = (long) _OpenLibrary(l_libname + 1, 0L);
  268.     if (LayersBase == NULL) {
  269.         writes(l_libname);
  270.         return 0;
  271.     }
  272.  
  273.     /* signal from input event handler to main code */
  274.     mySignal = AllocSignal(-1L);
  275.     if (mySignal == -1) {
  276.         writes("!allocate a signal bit.");
  277.         return 0;
  278.     }
  279.  
  280.     /* a signal to this port will terminate us */
  281.     myPort = CreatePort(port_name + 1, 0L);
  282.     if (myPort == NULL) {
  283.         writes(port_name);
  284.         return 0;
  285.     }
  286.  
  287.     /* port to the input.device */
  288.     inpPort = CreatePort((char *) NULL, 0L);
  289.     if (inpPort == NULL) {
  290.         writes("^input.device port.");
  291.         return 0;
  292.     }
  293.  
  294.     /* need an i/o request */
  295.     inpReq = CreateStdIO(inpPort);
  296.     if (inpReq == NULL) {
  297.         writes("^input.device i/o request.");
  298.         return 0;
  299.     }
  300.  
  301.     /* open input.device */
  302.     stat = OpenDevice(i_devname + 1, 0L, inpReq, 0L);
  303.     if (stat != 0) {
  304.         writes(i_devname);
  305.         return 0;
  306.     }
  307.  
  308.     /* port to the console.device */
  309.     conPort = CreatePort((char *) NULL, 0L);
  310.     if (!conPort) {
  311.         writes("^console.device port.");
  312.         return 0;
  313.     }
  314.  
  315.     /* need an i/o request */
  316.     conReq = CreateStdIO(conPort);
  317.     if (!conReq) {
  318.         writes("^console.device i/o request.");
  319.         return 0;
  320.     }
  321.  
  322.     /* open console.device */
  323.     stat = OpenDevice(c_devname + 1, -1L, conReq, 0L);
  324.     if (stat != 0) {
  325.         writes(c_devname);
  326.         return 0;
  327.     }
  328.  
  329.     /* check for consolebase */
  330.     ConsoleBase = (struct ConsoleBase *) conReq->io_Device;
  331.     if (!ConsoleBase) {
  332.         writes("!find ConsoleBase.");
  333.         return 0;
  334.     }
  335.  
  336.     /* handler command stuff */
  337.     handler.is_Code = handlerCode;
  338.     handler.is_Node.ln_Pri = 51;
  339.  
  340.     /* install new input event handler */
  341.     inpReq->io_Command = IND_ADDHANDLER;
  342.     inpReq->io_Data = (APTR) &handler;
  343.  
  344.     stat = DoIO(inpReq);
  345.     if (stat != 0) {
  346.         writes("ADDHANDLER request failed.");
  347.         return 0;
  348.     }
  349.     handlerIn = 1;
  350.  
  351.     /* function catchers */
  352.  
  353.     oldRectFill = SetFunction(GfxBase, (long) lvoRectFill, myRectFill);
  354.     if (oldRectFill == 0) {
  355.         writes("!replace RectFill()");
  356.         return 0;
  357.     }
  358.  
  359.     oldScrollRaster = SetFunction(GfxBase, (long) lvoScrollRaster,
  360.                                     myScrollRaster);
  361.     if (oldScrollRaster == 0) {
  362.         writes("!replace ScrollRaster()");
  363.         return 0;
  364.     }
  365.  
  366.     oldCloseWindow = SetFunction(IntuitionBase, (long) lvoCloseWindow,
  367.                                     myCloseWindow);
  368.     if (oldCloseWindow == 0) {
  369.         writes("!replace CloseWindow()");
  370.         return 0;
  371.     }
  372.  
  373.     return 1;
  374. }
  375.  
  376. /*********************************************/
  377.  
  378. int jump(mode)
  379. int mode;
  380. {
  381.     char ch;
  382.  
  383.     while (0 < msgp->alen--) {
  384.         ch = *msgp->aptr++;
  385.         if ((ch != ' ' && ch != '\t' && ch != '\n') == mode)
  386.             return ch;
  387.     }
  388.     return 0;
  389. }
  390.  
  391. /*********************************************/
  392.  
  393. int innum(base)
  394. int base;
  395. {
  396.     int result, neg, ch;
  397.  
  398.     result = 0;
  399.     ch = jump(1);
  400.     if (!ch)
  401.         return 0;
  402.  
  403.     neg = ch == '-';
  404.     if ((neg || ch == '+') && 0 < msgp->alen--)
  405.         ch = *msgp->aptr++;
  406.  
  407.     while (1) {
  408.         ch -= '0';
  409.         if (9 < ch)
  410.             ch -= 7;    /* was 'A'-'F' */
  411.         if (15 < ch)
  412.             ch -= 32;    /* was 'a'-'f' */
  413.  
  414.         if (ch < 0 || base <= ch) {
  415.             msgp->alen++;    /* ungetc */
  416.             msgp->aptr--;
  417.             break;
  418.         }
  419.  
  420.         result = result * base + ch;
  421.  
  422.         if (msgp->alen-- <= 0)
  423.             break;
  424.  
  425.         ch = *msgp->aptr++;
  426.     }
  427.     return neg ? -result : result;
  428. }
  429.  
  430. /*********************************************/
  431.  
  432. usage()
  433. {
  434. writes("Usage: snipit [opts]");
  435. writes("where opts can be any of:");
  436. writes("   ? or h         Help; this text");
  437. writes("   q              Quit; remove SnipIt from the system");
  438. writes("   p \"prestring\"  When pasting using Command-B key, insert");
  439. writes("                  \"prestring\" before each line.  In quotes");
  440. writes("   l 1 or 0       Lock layer (or don't) while snipping");
  441. writes("   u +/-number    Adjust cell x position in console windows");
  442. writes("   v +/-number    Adjust cell y position in console windows");
  443. writes("   x +/-number    Adjust cell x position in non-console windows");
  444. writes("   y +/-number    Adjust cell y position in non-console windows");
  445. writes("   a hex-number   Qualifier for Command-A key (default LEFT-AMIGA)");
  446. writes("   b hex-number   Qualifier for Command-B key (default LEFT-ALT)");
  447. writes("");
  448. writes("Defaults are:  p\"> \" l0 u0 v0 x0 y0 a0040 b0010");
  449. }
  450.  
  451. /*********************************************/
  452.  
  453. int options()
  454. {
  455.     char *cp;
  456.     int temp, ch;
  457.  
  458.     msgp->done = msgp->huh = msgp->off = 0;
  459.  
  460.     do {
  461.         /* locate a char after whitespace */
  462.         ch = jump(1);                    /* advance to 1st non-white */
  463.  
  464.         if ('A' <= ch && ch <= 'Z')
  465.             ch = ch - 'A' + 'a';        /* tolower */
  466.  
  467.         /* act on char */
  468.         switch (ch) {
  469.  
  470.         case 0:        break;
  471.  
  472.         case 'q':    msgp->done = 1;
  473.                     return 0;            /* die */
  474.  
  475.         case 'p':    cp = preString;
  476.                     ch = jump(1);        /* delim char */
  477.                     if (ch) {
  478.                         while (0 < msgp->alen-- &&
  479.                                (*cp = *msgp->aptr++) != ch) {
  480.                             cp++;
  481.                             if (preString + PRE_SIZE <= cp)
  482.                                 break;
  483.                         }
  484.                     }
  485.                     *cp = 0;
  486.                     break;
  487.  
  488.         case 'x':    if (snip == WIN_SNIP)
  489.                         clearHi();
  490.                     msgp->off = 1;
  491.                     win_offx += innum(10);
  492.                     break;
  493.  
  494.         case 'y':    if (snip == WIN_SNIP)
  495.                         clearHi();
  496.                     msgp->off = 1;
  497.                     win_offy += innum(10);
  498.                     break;
  499.  
  500.         case 'u':    if (snip == CON_SNIP)
  501.                         clearHi();
  502.                     msgp->off = 1;
  503.                     con_offx += innum(10);
  504.                     break;
  505.  
  506.         case 'v':    if (snip == CON_SNIP)
  507.                         clearHi();
  508.                     msgp->off = 1;
  509.                     con_offy += innum(10);
  510.                     break;
  511.  
  512.         case 'a':    if (temp = innum(16));
  513.                         cmd1 = temp;
  514.                     break;
  515.  
  516.         case 'b':    if (temp = innum(16));
  517.                         cmd2 = temp;
  518.                     break;
  519.  
  520.         case 'l':    ch = jump(1);        /* first char */
  521.                     if (ch)
  522.                         lock_layer = ch == '1';
  523.                     break;
  524.  
  525.         case 'w':    ch = jump(1);        /* first char */
  526.                     if (ch)
  527.                         windows = ch == '1';
  528.                     break;
  529.  
  530.         default:    msgp->huh = 1;        /* newline, too - end of string */
  531.                     break;
  532.         }
  533.  
  534.     } while (jump(0));                    /* advance to whitespace */
  535.  
  536.     if (msgp->off) {
  537.         win_offx = win_offx < -32 ? -32 : 32 < win_offx ? 32 : win_offx;
  538.         win_offy = win_offy < -32 ? -32 : 32 < win_offy ? 32 : win_offy;
  539.         con_offx = con_offx < -32 ? -32 : 32 < con_offx ? 32 : con_offx;
  540.         con_offy = con_offy < -32 ? -32 : 32 < con_offy ? 32 : con_offy;
  541.  
  542.         msgp->w_offx = win_offx;
  543.         msgp->w_offy = win_offy;
  544.         msgp->c_offx = con_offx;
  545.         msgp->c_offy = con_offy;
  546.     }
  547.  
  548.     return 1;    /* i.e., keep running */
  549. }
  550.  
  551. /*********************************************/
  552.  
  553. outnum(n)
  554. int n;
  555. {
  556.     char d;
  557.  
  558.     if (n < 0) {
  559.         n = -n;
  560.         _Write(output, "-", 1L);
  561.     }
  562.     if (n > 9) {
  563.         d = n / 10 + '0';
  564.         _Write(output, &d, 1L);
  565.     }
  566.     d = n % 10 + '0';
  567.     _Write(output, &d, 1L);
  568. }
  569.  
  570. /*********************************************/
  571.  
  572. currAdjust(type, x, y)
  573. char *type;
  574. int x, y;
  575. {
  576.     _Write(output, type, 7L);
  577.     _Write(output, " adjustment now: x=", 19L);
  578.     outnum(x);
  579.     _Write(output, ",y=", 3L);
  580.     outnum(y);
  581.     _Write(output, "\n", 1L);
  582. }
  583.  
  584. /*********************************************/
  585.  
  586. checkStatus()
  587. {
  588.     if (myMsg.huh)
  589.         writes(huh_msg);
  590.  
  591.     else if (myMsg.done)
  592.         writes("_ cancelled.");
  593.  
  594.     else if (myMsg.off) {
  595.         currAdjust("Console", myMsg.c_offx, myMsg.c_offy);
  596.         currAdjust("Window ", myMsg.w_offx, myMsg.w_offy);
  597.     }
  598. }
  599.  
  600. /*********************************************/
  601.  
  602. _main(alen, aptr)    /* DOSBase and ExecBase opened already by crt0.o */
  603. long alen;
  604. char *aptr;
  605. {
  606.     static int pass;
  607.     int keep_going;
  608.     long sige, sigt;
  609.     struct MsgPort *port, *rport;
  610.  
  611.     /* sever seglists */
  612.     do_detach(&alen, &aptr);
  613.  
  614.     myMsg.alen = alen;
  615.     myMsg.aptr = aptr;
  616.  
  617.     /* help requested?? */
  618.     if (*aptr == '?' || *aptr == 'h')
  619.         usage();
  620.  
  621.     /* installed already? if so, pass arguments */
  622.     else if (port = FindPort(port_name + 1)) {    
  623.  
  624.         if (alen <= 1)
  625.             writes("_ already installed!");
  626.  
  627.         else {
  628.             myMsg.m.mn_ReplyPort = rport = CreatePort(NULL, 0L);
  629.             if (!rport)
  630.                 writes("^a port");
  631.  
  632.             else {
  633.                 PutMsg(port, &myMsg);
  634.                 _WaitPort(rport);        /* wait for reply */
  635.                 _GetMsg(rport);
  636.                 DeletePort(rport);
  637.  
  638.                 /* check return stats */
  639.                 checkStatus();
  640.             }
  641.         }
  642.     }
  643.  
  644.     /* install & deal with args */
  645.     else if (init()) {
  646.  
  647.         msgp = &myMsg;
  648.         if (options() && !myMsg.huh) {
  649.  
  650.             writes("_ installed.  \xA9 1988 - Scott Evernden");
  651.  
  652.             running = 1;
  653.  
  654.             /* signals which mean something */
  655.             sige = 1L << mySignal;            /* request for recognition */
  656.             sigt = 1L << myPort->mp_SigBit;    /* options message */
  657.  
  658.             /* process requests for handler code
  659.              * while awaiting options signal
  660.              */
  661.  
  662.             keep_going = 1;
  663.             while (keep_going) {
  664.  
  665.                 if (Wait(sige | sigt) == sige) {
  666.                     buildEvents();
  667.                     jobFlag = 0;        /* lower active flag */
  668.                 }
  669.                 else while (msgp = (struct MyMessage *) GetMsg(myPort)) {
  670.                     keep_going = options();
  671.                     _ReplyMsg(msgp);
  672.                 }
  673.             }
  674.         }
  675.  
  676.         else { 
  677.             if (myMsg.huh)
  678.                 writes(huh_msg);
  679.  
  680.             writes("_ not installed.");
  681.         }
  682.     }
  683.  
  684.     running = 1;
  685.  
  686.     /* terminate */
  687.     Delay(10L);
  688.     fini();
  689. }
  690.  
  691.